import { Button, Collapse, Divider, Form, Input, InputNumber, Modal, Select } from 'antd';
import React, { useState, useEffect, useCallback, useRef } from 'react'
import _, { divide, set } from 'lodash'
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import AddProperty from './AddProperty';
import { FrameSty } from './style';

enum VarType {
  String = 'String',
  Number = 'Number',
  Boolean = 'Boolean',
  Array = 'Array',
  Object = 'Object',
}

const selectValueType = [
  {
    label: '字符串',
    value: VarType.String
  },
  {
    label: '数字',
    value: VarType.Number
  },
  {
    label: '布尔',
    value: VarType.Boolean
  },
  {
    label: '数组',
    value: VarType.Array
  },
  {
    label: '对象',
    value: VarType.Object
  },
]

const selectNameType = [
  {
    label: '字符串',
    value: VarType.String
  },
]
type AddOrEditGlobalVarProps = {
  type: 'add' | 'edit',
  handleCancel: () => void,
  handleOk: (type: 'add' | 'edit', data: any) => void,
}
export default function AddOrEditGlobalVar(props: AddOrEditGlobalVarProps) {
  const { handleCancel, handleOk = () => { }, type } = props;
  const [isOpen, setIsOpen] = useState<boolean>(false)
  const [collapseState, setCollapseState] = useState<any>({});
  const [data, setData] = useState<any>({});
  const [isAddPropertyOpen, setIsAddPropertyOpen] = useState<boolean>(false);
  let objectQueue = useRef<string[]>([])

  useEffect(() => {
    setData({
      property: 'userInfo',
      value: {
        name: '张三',
        age: 18,
        male: true,
        class: {
          name: '一班',
          student: 30,
          days: [1, 2, 3, 4, 5]
        }
      }
    })
  }, [])

  /**
  * @description 获取值的类型
  * @param value 值 {any}
  * @returns {VarType}
  */
  const getValuetype = useCallback((value: any): VarType => {
    let type = Object.prototype.toString.call(value)
    let typeMap: any = {
      '[object String]': VarType.String,
      '[object Number]': VarType.Number,
      '[object Boolean]': VarType.Boolean,
      '[object Array]': VarType.Array,
      '[object Object]': VarType.Object,
    }
    return typeMap[type]
  }, [])

  /**
  * @description 是否的对象和数组
  * @param value 值 {VarType} 
  * @returns {boolean}
  */
  const isObjectOrArray = useCallback((value: VarType): boolean => {
    let type = getValuetype(value)
    return [VarType.Object, VarType.Array].includes(type)
  }, [])

  /** 选择的类型发生改变*/
  const changeSelect = useCallback((value: VarType, queue: string[]) => {
    let condition: Record<VarType, any> = {
      [VarType.String]: '',
      [VarType.Number]: 0,
      [VarType.Boolean]: false,
      [VarType.Array]: [],
      [VarType.Object]: {},
    }
    let newData = _.cloneDeep(data)
    //更具队列找到对应的值并修改newData的值
    let current = newData
    queue.forEach((key: string, index: number) => {
      if (index === queue.length - 1) {
        current[key] = condition[value]
      } else {
        current = current[key]
      }
    })
    setData(newData)
  }, [data])

  /** 添加新的一项*/
  const addNewItem = useCallback((e: any, queue: string[], type: VarType) => {
    let key = queue.join('-');
    if (!collapseState.hasOwnProperty(key) || collapseState[key] === false) {

    } else {
      e.stopPropagation()
    }
    if (type === VarType.Object) {
      objectQueue.current = queue
      setIsAddPropertyOpen(true)
      return
    }

    let newData = _.cloneDeep(data)
    //更具队列找到对应的值并修改newData的值
    let current = newData
    queue.forEach((key: string, index: number) => {
      if (index === queue.length - 1) {
        current[key].push('')
      } else {
        current = current[key]
      }
    })
    setData(newData)
  }, [data, collapseState])

  /** 删除一项*/
  const delNewItem = useCallback((queue: string[]) => {
    let newData = _.cloneDeep(data)
    //更具队列找到对应的值并修改newData的值
    let current = newData
    queue.forEach((key: string, index: number) => {
      if (index === queue.length - 1) {
        if (getValuetype(current) === VarType.Array) {
          //使用lodash删除数组的元素
          _.pullAt(current, Number(key))
        }
        if (getValuetype(current) === VarType.Object) {
          //使用lodash删除对象的属性
          _.unset(current, key)
        }
      } else {
        current = current[key]
      }
    })
    setData(newData)
  }, [data])

  /** 改变值*/
  const valueInputChange = useCallback((value: any, queue: string[]) => {
    let newData = _.cloneDeep(data)
    //更具队列找到对应的值并修改newData的值
    let current = newData
    queue.forEach((key: string, index: number) => {
      if (index === queue.length - 1) {
        current[key] = value
      } else {
        current = current[key]
      }
    })
    // console.log(newData);
    setData(newData)
  }, [data])

  /** 获取对应类型的组件*/
  const getTypeComponent = useCallback((value: any, queue: string[]) => {
    let type = getValuetype(value)
    let typeMap: Record<any, React.ReactNode> = {
      [VarType.String]: <Input
        defaultValue={value}
        style={{
          width: '120px'
        }}
        onChange={(e) => {
          valueInputChange(e.target.value, queue)
        }}
      />,
      [VarType.Number]: <InputNumber
        defaultValue={value}
        style={{
          width: '120px'
        }}
        onChange={(value) => {
          valueInputChange(value, queue)
        }}
      />,
      [VarType.Boolean]: <Select
        defaultValue={value}
        style={{ width: 120 }}
        options={[
          { value: true, label: 'true' },
          { value: false, label: 'false' }
        ]}
        onChange={(value) => {
          valueInputChange(value, queue)
        }}
      />,
    }
    return typeMap[type]
  }, [valueInputChange])

  /** 改变折叠状态*/
  const changeCollapseStatus = useCallback((data: string, queue: string[]) => {
    if (data.length === 0) {
      setCollapseState((prev: any) => {
        let newState = _.cloneDeep(prev)
        newState[queue.join('-')] = false
        return newState
      })
    } else {
      setCollapseState((prev: any) => {
        let newState = _.cloneDeep(prev)
        newState[queue.join('-')] = true
        return newState
      })
    }
  }, [])

  /** 递归渲染*/
  const Render = useCallback((renderData: any, serial: number, queue: string[]) => {
    return (
      <div className='list'>
        {
          Object.keys(renderData).map((key: string, index: number) => {
            return (
              <div
                className='item'
                key={index}
                style={{
                  paddingLeft: `${serial * 18 + (isObjectOrArray(renderData[key]) ? 0 : 18)}px`,
                }}
              >
                <Collapse
                  ghost={true}
                  style={{
                    width: '100%',
                  }}
                  size='small'
                  collapsible='header'
                  onChange={(keyOne: any) => {
                    changeCollapseStatus(keyOne, [...queue, key])
                  }}
                  items={
                    [{
                      key: '1',
                      showArrow: isObjectOrArray(renderData[key]),
                      extra: <>
                        <Select
                          defaultValue={getValuetype(renderData[key])}
                          bordered={false}
                          size='small'
                          style={{
                            width: 120
                          }}
                          options={queue.length == 0 &&
                            key === 'property' ? selectNameType : selectValueType}
                          onChange={(value) => {
                            changeSelect(value, [...queue, key])
                          }}
                        />
                      </>,
                      label: < >
                        <Form
                          layout="horizontal"
                          style={{
                            height: '32px'
                          }}
                        >
                          <Form.Item label={
                            <div
                              onClick={(e) => {
                                e.stopPropagation()
                              }}
                              style={{
                                width: '100px',
                                height: '32px',
                                padding: '0px 5px',
                                textAlign: 'left',
                                lineHeight: '32px',
                                // 下划线
                                borderBottom: '2px solid #d9d9d9',
                                cursor: 'not-allowed'
                              }}
                            >
                              {queue.length == 0 ?
                                key === 'property' ? '变量名' : '值'
                                : key
                              }
                            </div>
                          }>
                            <>
                              {isObjectOrArray(renderData[key]) ?
                                <div
                                  style={{
                                    marginLeft: '5px'
                                  }}
                                >
                                  <span onClick={(e) => {
                                    e.stopPropagation()
                                  }}>{getValuetype(renderData[key])}
                                  </span>
                                  <Button
                                    icon={<PlusOutlined />}
                                    size='small'
                                    style={{
                                      marginLeft: '10px'
                                    }}
                                    onClick={(e) => {
                                      addNewItem(e, [...queue, key], getValuetype(renderData[key]))
                                    }}
                                  />
                                </div>
                                : <div style={{
                                  display: 'flex',
                                  alignItems: 'center',
                                }}>
                                  {getTypeComponent(renderData[key], [...queue, key])}
                                  {
                                    queue.length > 0 &&
                                    <Button
                                      style={{
                                        marginLeft: '10px'
                                      }}
                                      icon={<DeleteOutlined />}
                                      onClick={() => {
                                        delNewItem([...queue, key])
                                      }}
                                    />
                                  }
                                </div>
                              }
                            </>
                          </Form.Item>
                        </Form>
                      </>,
                      children: <>{
                        isObjectOrArray(renderData[key])
                          ? <div style={{
                            marginTop: "5px"
                          }}>
                            {Render(renderData[key], serial + 1, [...queue, key])}
                          </div>
                          : null
                      }
                      </>
                    }]
                  }
                >
                </Collapse>
              </div>
            )
          })
        }
      </div>
    )
  }, [changeSelect, addNewItem, delNewItem, getTypeComponent, changeCollapseStatus])

  /** 点击完成*/
  const onOk = useCallback(() => {
    const reg = /^\d+$/
    if (reg.test(data.property)) {
      console.log('属性名不能为数字');
      return
    }
    if (!data.property.trim()) {
      console.log('属性名不能为空');
      return
    }
    setIsOpen(false)
    setData({
      property: data.property,
      value: data.value
    })
    handleOk(type, data)
  }, [data, type])

  /** 输入属性名完成*/
  const onAddPropertyOk = useCallback((value: string) => {
    setIsAddPropertyOpen(false)
    let newData = _.cloneDeep(data)
    //更具队列找到对应的值并修改newData的值
    let current = newData
    objectQueue.current.forEach((key: string, index: number) => {
      if (index === objectQueue.current.length - 1) {
        if (Object.keys(current[key]).includes(value)) {
          console.log('已经存在');
          return
        } else {
          current[key][String(value)] = ''
        }
      } else {
        current = current[key]
      }
    })
    setData(newData)
  }, [data])

  return (
    <>
      <Button onClick={() => {
        setIsOpen(true)
      }}>点击编辑按钮</Button>
      <Modal
        title={type === 'add' ? '添加全局变量' : '编辑全局变量'}
        width='600px'
        open={isOpen}
        onCancel={() => {
          setIsOpen(false)
        }}
        onOk={onOk}
        destroyOnClose={true}
      >
        <FrameSty>
          {Render(data, 0, [])}
        </FrameSty>
      </Modal>

      <AddProperty
        isOpen={isAddPropertyOpen}
        handleCancel={() => {
          setIsAddPropertyOpen(false)
        }}
        handleOk={onAddPropertyOk}
      />
    </>
  )
}